package com.logic.modular.game.battle.panel.attribute.domain;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import cn.hutool.extra.spring.SpringUtil;
import com.comment.exception.ServiceException;
import com.logic.comment.util.BeanUtil;
import com.logic.modular.game.battle.panel.Battle;
import com.logic.modular.game.battle.info.FiledName;
import com.comment.pojo.domain.logic.domain.PlayerHero;
import com.comment.pojo.domain.logic.core.CoreSkill;
import com.comment.pojo.domain.logic.core.CoreSkillStar;
import com.logic.modular.gameCore.cultivate.skill.service.CoreSkillServiceImpl;
import com.logic.modular.gameCore.cultivate.skill.controller.CoreSkillStarServiceImpl;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import javax.validation.constraints.NotNull;

/**
 * 武将属性
 */
@Slf4j
@ApiModel("武将属性")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PlayerHeroAttribute implements Serializable {
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    private Integer battleCount;
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    @ApiModelProperty("武将id")
    private Long id;

    @ApiModelProperty("0:防守,1:进攻")
    private Integer rankCamp;
    @ApiModelProperty("账号uid")
    public Long uid;

    @ApiModelProperty("武将id")
    public Long coreHeroId;

    @ApiModelProperty("玩家命名")
    public String name;
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    @ApiModelProperty("武力")
    public Double att;

    @ApiModelProperty("防御")
    public Double def;

    @ApiModelProperty("策略")
    public Double magic;

    @ApiModelProperty("先攻值")
    public Double speed;

    @ApiModelProperty("统帅")
    public Double des;

    @ApiModelProperty("兵力")
    public Long currentForce;
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    @ApiModelProperty("所有伤害")
    public Double all1 = 1.0;
    public Double all0 = 1.0;

    @ApiModelProperty("造成普通攻击伤害")
    public Double attack1 = 1.0;
    @ApiModelProperty("受到普通攻击伤害")
    public Double attack0 = 1.0;

    @ApiModelProperty("物理伤害")
    public Double physics1 = 1.0;
    public Double physics0 = 1.0;

    @ApiModelProperty("策略伤害")
    public Double strategy1 = 1.0;
    public Double strategy0 = 1.0;

    @ApiModelProperty("恢复率")
    public Double recover1 = 1.0;
    public Double recover0 = 1.0;

    @ApiModelProperty("主动战法")//
    public Double activeIncrease1 = 1.0;
    public Double activeIncrease0 = 1.0;

    @ApiModelProperty("上回合死亡兵力")
    public double lastDeadForces = 0.0;

    @ApiModelProperty("前回合死亡兵力")
    public double currentDeadForces = 0.0;

    @ApiModelProperty("无视防御效果")
    public Double igDefensiveDefense = 1.0;

    @ApiModelProperty("无视策略防御效果")
    public Double igStrategicDefense = 1.0;

    @ApiModelProperty("无视物理防御效果")
    public Double igPhysicalDefense = 1.0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    @ApiModelProperty("武将技能信息 k:技能卡槽 v:技能信息")
    private SkillSlot skillSlot;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public static class SkillSlot {
        private Map<Integer, CoreSkill> skillSlot = new HashMap<>();
        private Map<Integer, CoreSkillStar> skillStarSlot = new HashMap<>();
    }

    public void obtainSkillInfo(PlayerHero playerHero) {
        CoreSkillStarServiceImpl skillStarService = SpringUtil.getBean(CoreSkillStarServiceImpl.class);
        CoreSkillServiceImpl coreSkillService = SpringUtil.getBean(CoreSkillServiceImpl.class);
        Map<Integer, CoreSkill> skillMap = new HashMap<>();
        Map<Integer, CoreSkillStar> skillStarMap = new HashMap<>();

        Long skillStrId = playerHero.getSkill();
        CoreSkillStar skillStar = skillStarService.get(skillStrId);
        CoreSkill skill = coreSkillService.getCache(skillStar.getSkillId());
        if (skill != null) skillMap.put(0, skill);
        skillStarMap.put(0, skillStar);

        Long skillSlot1 = playerHero.getSkillSlot1();
        if (skillSlot1 > 0) {
            CoreSkillStar skillStar1 = skillStarService.get(skillSlot1);
            CoreSkill skill1 = coreSkillService.getCache(skillStar1.getSkillId());
            if (skill1 != null) skillMap.put(1, skill1);
            skillStarMap.put(1, skillStar1);
        }

        Long skillSlot2 = playerHero.getSkillSlot2();
        if (skillSlot2 > 0) {
            CoreSkillStar skillStar2 = skillStarService.get(skillSlot2);
            CoreSkill skill2 = coreSkillService.getCache(skillStar2.getSkillId());
            if (skill2 != null) skillMap.put(2, skill2);
            skillStarMap.put(2, skillStar2);
        }
        skillSlot = new SkillSlot(skillMap, skillStarMap);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    @ApiModelProperty("上回合死亡数量")
    private Long lastDead = 0L;
    private Long thisDead = 0L;

    @ApiModelProperty("队伍位置")
    private Integer rankOrder;

    @ApiModelProperty("战斗编号")
    private String battleUUID;

    @ApiModelProperty("当前所处回合")
    private Integer round;

    @ApiModelProperty("当前所处阶段")
    private Integer phase;

    @ApiModelProperty("战斗技能次数")

    private Map<Long, Integer> skillBattleCount = new HashMap<>();
    private Map<Long, Integer> skillRoundCount = new HashMap<>();

    public Map<Long, Object> behaviorMap = new HashMap<>();// 回合行为 k:行为
    private Map<Long, Integer> roundBehavior = new ConcurrentHashMap<>();// 回合行为计数器 k:行为 v:次数
    private Map<Integer, Map<Long, Integer>> logRoundBehavior = new ConcurrentHashMap<>();// 历史回合行为计数器 k:回合 v:回合行为计数器
    private Map<Long, Integer> battleBehavior = new ConcurrentHashMap<>();// 战斗行为计数器

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * 记录行为次数
     *
     * @param behaveType 行为类型id
     */
    public void logBehave(Long behaveType) {
        roundBehavior.put(behaveType, roundBehavior.getOrDefault(behaveType, 0) + 1);
        logRoundBehavior.put(round, new ConcurrentHashMap<>(roundBehavior));
        battleBehavior = logRoundBehavior.values().stream()
                .flatMap(map -> map.entrySet().stream())
                .collect(Collectors.toConcurrentMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        Integer::sum // 如果有重复的键，则将值相加
                ));
    }

    private Map<Long, EffectStatus> status = new HashMap<>();// 当前拥有的效果

    /**
     * key: 技能类型
     * value: 暂定
     */
    @ApiModelProperty("当前所处事件")// 这里指技能
    public Map<Integer, String> event = new HashMap<>();


    /**
     * 刷新回合信息
     */
    public void refreshRoundInfo() {
        Battle battle = Battle.get(battleUUID);
        round = battle.getRound();

        skillRoundCount.forEach((k, v) -> skillRoundCount.put(k, 0));
        lastDead = thisDead;
        thisDead = 0L;
    }

    /**
     * 改变属性
     *
     * @return
     */
    public Object attributeUpdate(
            @NotNull(message = "字段名") String fieldName,
            @NotNull(message = "变动值") Object value,
            @NotNull(message = "1:造成 0:受到") Integer direction,
            @NotNull(message = "成功") Integer isSuccessful,
            @NotNull(message = "效果原因") Long effectTypeId
    ) {
        if (effectTypeId == null) {
            throw new ServiceException("技能效果类型id不能为空");
        }
        if (direction == 1) {// 造成
            long behave = effectTypeId;
            if (isSuccessful == 1) {
                behave = behave + 100L;
            }
            behaviorMap.put(behave, value);
        } else { // 受到
            long behave = -effectTypeId;
            if (isSuccessful == 1) {
                behave = behave - 100L;
                if (!fieldName.isEmpty()) {
                    return attributeUpdate(fieldName, value);
                } else {
                    log.warn("技能无数值变动");
                }
            }
            behaviorMap.put(behave, value);
        }
        return null;
    }


    /**
     * 扣血
     */
    public Object bloodDeduction(
            @NotNull(message = "变动值") Object value,
            @NotNull(message = "1:造成 0:受到") Integer direction,
            @NotNull(message = "成功") Integer isSuccessful,
            @NotNull(message = "效果原因") Long effectTypeId
    ) {
        if (effectTypeId == null) {
            throw new ServiceException("技能效果类型id不能为空");
        }

        long behave;
        if (direction == 1) {// 造成
            behave = effectTypeId;
            if (isSuccessful == 1) {
                behave = behave + 100L;
            }
        } else { // 受到
            behave = -effectTypeId;
            if (isSuccessful == 1) {
                behave = behave - 100L;
                return BeanUtil.updateField(this, "currentForce", value);
            }
        }
        behaviorMap.put(behave, value);
        return null;
    }


    public void logSkillCount(Long coreSkillStarId) {
        boolean b = skillBattleCount.containsKey(coreSkillStarId);
        if (b) {
            skillBattleCount.put(coreSkillStarId, skillBattleCount.get(coreSkillStarId) + 1);
        } else {
            skillBattleCount.put(coreSkillStarId, 1);
        }
        boolean b1 = skillRoundCount.containsKey(coreSkillStarId);
        if (b1) {
            skillRoundCount.put(coreSkillStarId, skillRoundCount.get(coreSkillStarId) + 1);
        } else {
            skillRoundCount.put(coreSkillStarId, 1);
        }
    }

    public void logPhase() {
        log.info("-------------------------{}-{}:{}阶段-------------------------",
                id, phase, FiledName.phaseMap.get(phase)
        );
    }


    /**
     * 清除行为
     */
    public void clearAction() {
        behaviorMap = new HashMap<>();
        behaviorMap = new HashMap<>();
        phase = 0;
    }


    public Double obtainPhysicsAttackIncrease() {
        return physics1 + all1;
    }

    public Double obtainPhysicsAttackDecrease() {
        return physics0 + all0;
    }

    public Double obtainStrategyAttackIncrease() {
        return strategy1 + all1;
    }

    public Double obtainStrategyAttackDecrease() {
        return strategy0 + all0;
    }

    public Double obtainRecoverIncrease() {
        return recover1;
    }

    public Double obtainRecoverDecrease() {
        return recover0;
    }

    /**
     * 改变属性
     *
     * @return
     */
    public Object attributeUpdate(
            @NotNull(message = "字段名") String fieldName,
            @NotNull(message = "变动值") Object value
    ) {
        return BeanUtil.updateField(this, fieldName, value);
    }
}